﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;
using System.Threading.Tasks;

namespace SimpleReactiveObjects.Test.SimpleReactiveObjects
{
    [TestClass]
    public class ExpressionTestScenarios
    {
        public class Settings : IDisposable
        {
            private readonly CompositeDisposable disposables;

            public Settings()
            {
                Enabled = new ReactiveVariable<bool>();

                disposables = new CompositeDisposable()
                {
                    Enabled,
                };
            }

            public ReactiveVariable<bool> Enabled { get; private set; }

            public void Dispose()
            {
                disposables.Dispose();
            }
        }

        public class State : IDisposable
        {
            private readonly CompositeDisposable disposables;

            public State(Settings settings)
            {
                Settings = settings;
                TemporarilyDisabled = new ReactiveVariable<bool>();
                Enabled = Observable.CombineLatest(Settings.Enabled, TemporarilyDisabled, (enabled, temporarilyDisabled) => enabled && (!temporarilyDisabled))
                                    .ToReactiveExpression();

                disposables = new CompositeDisposable()
                {
                    TemporarilyDisabled,
                    Enabled,
                };
            }

            public Settings Settings { get; private set; }

            public ReactiveVariable<bool> TemporarilyDisabled { get; private set; }

            public ReactiveExpression<bool> Enabled { get; private set; }

            public void Dispose()
            {
                disposables.Dispose();
            }
        }

        [TestMethod]
        public void TestMethod1()
        {
            using (var disposables = new CompositeDisposable())
            {
                var settings = new Settings();
                var state = new State(settings);

                disposables.Add(settings);
                disposables.Add(state);


                Action log = () =>
                {
                    Debug.Indent();
                    Debug.WriteLine("settings.Enabled = {0}", settings.Enabled);
                    Debug.WriteLine("state.TemporarilyDisabled = {0}", state.TemporarilyDisabled);
                    Debug.WriteLine("state.Enabled = {0}", state.Enabled);
                    Debug.Unindent();
                };

                Debug.WriteLine("Initial state");
                var d = state.Enabled.Subscribe(x => log());
                disposables.Add(d);


                Debug.WriteLine("Enable setting");
                settings.Enabled.Value = true;

                Debug.WriteLine("Disable temporally");
                state.TemporarilyDisabled.Value = true;
            }
        }
    }
}